package dts_tcp

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/sirupsen/logrus"
	"net"
	"time"
)

const (
	FlagTemperature DataFlag = iota
	FlagAntiStokes
	FlagStokes
)

const (
	CodeLogs                         Code = iota // 日志
	CodeServerChangeStatus                       // 添加一个客户端
	CodeClientAdd                                // 添加一个客户端
	CodeClientRemove                             // 删除一个客户端
	CodeClientChangeStatus                       // 客户端状态
	CodeClientAllStatus                          // 客户端状态
	CodeQueryRL                                  // 查询继电器分区信息
	CodeQueryAL                                  // 查询分区信息
	CodeQueryCA                                  // 查询设备通道运算参数
	CodeQueryCM                                  // 查询公共参数
	CodeQueryCode                                // 获取设备硬件码
	CodeQueryCH                                  // 查询通道信息
	CodeQueryIP                                  // 查询设备ip和端口
	CodeTemperature                              // 温度信号
	CodeFiberAlarm                               // 断纤报警
	CodeFiberBrokenAlarm                         // 断纤报警
	CodeConstantTemperatureAlarm                 // 高温定温报警
	CodeDifferentialTemperatureAlarm             // 高温差温报警
	CodeDeviceParams                             // 设备相关参数
)

const (
	Broken                  AlarmType = iota + 1 // 断纤
	ConstantTemperature                          // 常温报警
	DifferentialTemperature                      // 温差报警
)

const (
	DataFrameQueryRLStart   DataFrame = 0xA3 // 查询继电器分区信息
	DataFrameQueryALStart   DataFrame = 0xA4 // 查询分区信息
	DataFrameQueryCAStart   DataFrame = 0xA7 // 查询设备通道运算参数
	DataFrameQueryCMStart   DataFrame = 0xA8 // 查询公共参数
	DataFrameQueryCodeStart DataFrame = 0xB0 // 获取设备硬件码
	DataFrameQueryCHStart   DataFrame = 0xB5 // 查询通道信息
	DataFrameQueryIPStart   DataFrame = 0xB7 // 查询设备ip和端口

	DataFrameTemperatureStart                  DataFrame = 0xAA // 温度信号
	DataFrameFiberBrokenAlarmStart             DataFrame = 0xBC // 断纤报警
	DataFrameConstantTemperatureAlarmStart     DataFrame = 0xA6 // 高温定温报警
	DataFrameDifferentialTemperatureAlarmStart DataFrame = 0xA5 // 高温差温报警
	DataFrameDeviceParamsStart                 DataFrame = 0xA9 // 设备相关参数

	DataFrameYesStart DataFrame = 0xAF // yes指令
	DataFrameNoStart  DataFrame = 0xA0 // no指令

	DataFrameEnd DataFrame = 0x55 // 数据尾指针

	HeaderLength = 11 // 包头长度,包括当前包的总长度在内

	F = logrus.FatalLevel
	E = logrus.ErrorLevel
	W = logrus.WarnLevel
	I = logrus.InfoLevel
	D = logrus.DebugLevel
)

var (
	DataFrameStart = []DataFrame{
		DataFrameQueryRLStart,
		DataFrameQueryALStart,
		DataFrameQueryCAStart,
		DataFrameQueryCMStart,
		DataFrameQueryCHStart,
		DataFrameQueryCodeStart,
		DataFrameQueryIPStart,
		DataFrameTemperatureStart,
		DataFrameDeviceParamsStart,
		DataFrameFiberBrokenAlarmStart,
		DataFrameConstantTemperatureAlarmStart,
		DataFrameDifferentialTemperatureAlarmStart,
		DataFrameYesStart,
		DataFrameNoStart,
	}
	DataFrameFlag = []byte{0x7B, 0x07, 0xAF, 0xEC, 0x66, 0x48, 0xC5}
	_             = FlagStokes
	_             = FlagAntiStokes

	EDFCmdMA = func(current byte) []byte {
		return []byte(fmt.Sprintf("[E]>MA%d#", current))
	}

	// EDFCmdNET  网络测试命令
	EDFCmdNET = func() []byte {
		return []byte("[E]?ET#")
	}

	// EDFCmdCBCL  目标服务端的IP和端口号
	EDFCmdCBCL = func(local, remote string, port int) ([]byte, []byte, error) {
		l := net.ParseIP(local)
		r := net.ParseIP(remote)
		if l == nil || r == nil {
			return nil, nil, errors.New("本地IP或远程IP非法")
		}
		l = l.To4()
		r = r.To4()
		return []byte(fmt.Sprintf("[E]>CB%d|%d|%d|%d#", l[0], l[1], l[2], l[3])),
			[]byte(fmt.Sprintf("[E]>CL%d|%d|%d|%d|%d#", r[0], r[1], r[2], r[3], port)), nil
	}

	// DEVCmdUP
	//参数分别对应为通道号与上传数据类型，
	//0x000F 后四位作标志位d3,d2,d1,d0。
	//d0:temperature
	//d1:anti-stokes,
	//d2:stokes,
	//d3:device info.
	//标志位为0表示判断数据，
	//标志为1表示上传数据。
	//如[D]>UP0|15#,即第0通道上传以上所有四种数据，[D]>UP0|1#表示通道0只上传温度数据。
	DEVCmdUP = func(channelNumber, flag byte) []byte {
		return []byte(fmt.Sprintf("[D]>UP%d|%d#", channelNumber, flag))
	}

	// DEVCmdSA
	// 参数分别对应采样率（采样率200M）
	DEVCmdSA = func(samplingRate int) []byte {
		return []byte(fmt.Sprintf("[D]>SA%d#", samplingRate))
	}
	// DEVCmdDL [3]、[D]>DL%d#
	//设置内部光纤长度，可通过曲线查看实际内部光纤长度，在实际使用过程中，此参数已出厂设置好。机箱内部光纤长度是确定的。
	DEVCmdDL = func(fiberLength uint) []byte {
		return []byte(fmt.Sprintf("[D]>DL%d#", fiberLength))
	}

	// QUECmdDV 查询设备信息
	QUECmdDV = func(channelNumber byte) []byte {
		return []byte(fmt.Sprintf("[Q]<DV%d#", channelNumber))
	}
	// QUECmdCA 查询通道参数
	QUECmdCA = func(channelNumber byte) []byte {
		return []byte(fmt.Sprintf("[Q]<CA%d#", channelNumber))
	}
	// QUECmdCM 查询公共参数
	QUECmdCM = func(channelNumber byte) []byte {
		return []byte(fmt.Sprintf("[Q]<CM%d#", channelNumber))
	}
	// QUECmdAL 查询通道分区
	QUECmdAL = func(channelNumber byte) []byte {
		return []byte(fmt.Sprintf("[Q]<AL%d#", channelNumber))
	}
	// QUECmdRL 查询继电器
	QUECmdRL = func(relayNumber byte) []byte {
		return []byte(fmt.Sprintf("[Q]<RL%d#", relayNumber))
	}
	// QUECmdCH 通道数量信息
	QUECmdCH = func(relayNumber byte) []byte {
		return []byte("[Q]?CH#")
	}

	// QUECmdHID 设备硬件id
	QUECmdHID = func() []byte {
		return []byte("[Q]?ID#")
	}

	// QUECmdIP IP信息
	QUECmdIP = func() []byte {
		return []byte("[Q]?IP#")
	}

	// MRSCmdFW 复位
	MRSCmdFW = func() []byte {
		return []byte("[M]!FW#")
	}
	// MRSCmdXY 消音
	MRSCmdXY = func() []byte {
		return []byte("[M]!XY#")
	}
	// MRSCmdZJ 自检
	MRSCmdZJ = func() []byte {
		return []byte("[M]!ZJ#")
	}

	//
	//// MRSCmdRL 设置继电器
	//MRSCmdRL = func() []byte {
	//	return []byte("[M]!ZJ#")
	//}
	//// MRSCmdAM 报警设置
	//MRSCmdAM = func(channelNumber, areaNumber byte, start, end int, constantTemperature, differentialTemperature int) []byte {
	//	return []byte(fmt.Sprintf("[M]>AM%d|%d|%d|%d|%d|%d|%d|%d#", channelNumber, areaNumber, start, end, constantTemperature, differentialTemperature))
	//}
)

type Code int

type DataFrame int

func (d DataFrame) String() string {
	switch d {
	case DataFrameQueryRLStart:
		return "查询继电器分区信息命令"
	case DataFrameQueryALStart:
		return "查询分区信息命令"
	case DataFrameQueryCAStart:
		return "查询设备通道运算参数命令"
	case DataFrameQueryCMStart:
		return "查询公共参数命令"
	case DataFrameQueryCHStart:
		return "查询通道信息命令"
	case DataFrameQueryIPStart:
		return "查询设备IP命令"
	case DataFrameQueryCodeStart:
		return "查询硬件设备码命令"
	case DataFrameDeviceParamsStart:
		return "查询设备参数命令"
	case DataFrameTemperatureStart:
		return "光纤温度更新命令"
	case DataFrameFiberBrokenAlarmStart:
		return "断纤报警命令"
	case DataFrameConstantTemperatureAlarmStart:
		return "定温报警命令"
	case DataFrameDifferentialTemperatureAlarmStart:
		return "差温报警命令"
	case DataFrameYesStart:
		return "Yes命令"
	case DataFrameNoStart:
		return "No命令"
	default:
		return fmt.Sprintf("未知命令%X", int(d))
	}
}

type DataFlag byte // 数据位标识

type AlarmType byte // 报警类型

type MQTT struct {
	Servers  string // 服务器地址,支持多地址
	Username string // 用户名
	Password string // 密码
}

type Config struct {
	Debug        bool          // 调试模式
	Address      string        // 服务器地址
	address      *net.TCPAddr  // 服务器地址
	Precision    float32       // 报警位置精度
	FilterSignal bool          // 是否过滤信号数据
	Timeout      time.Duration // 连接超时间隔时间
	RetryCount   int           // 重试次数
}

// DeviceInfo 测温主机基本信息
type DeviceInfo struct {
	Address       string `json:"address,omitempty"`        // 设备主机地址
	DeviceCode    string `json:"device_code,omitempty"`    // 设备编码
	DeviceNumber  byte   `json:"device_number,omitempty"`  // 设备号
	ChannelId     int    `json:"channel_id,omitempty"`     // 通道号
	ChannelNumber byte   `json:"channel_number,omitempty"` // 通道号
}

// CommonParams 公共参数
type CommonParams struct {
	ChannelFlag int16  `json:"channel_flag"`
	EDFACurrent int16  `json:"edfa_current"`
	IP          string `json:"ip"`
	Port        int16  `json:"port"`
}

// ChannelTemperature 通道温度
type ChannelTemperature struct {
	Info         DeviceInfo `json:"info"`          // 设备信息
	Flag         DataFlag   `json:"flag"`          // 标志位
	ChannelCount byte       `json:"channel_count"` // 通道数
	Start        float32    `json:"start"`         // 开始位置
	End          float32    `json:"end"`           // 结束位置
	Temperatures []float32  `json:"temperatures"`  // 温度数据
	At           time.Time  `json:"at"`            // 报警时间
}

// ChannelCalculationParams 通道计算参数
type ChannelCalculationParams struct {
	FiberStart  float32 `json:"fiber_start"`  // 实际光纤开始长度
	FiberEnd    float32 `json:"fiber_end"`    // 实际光纤结束长度
	FiberLength float32 `json:"fiber_length"` // 光纤预估长度
	MeasureTime float32 `json:"measure_time"` // 测量时间
	AddTimes    int     `json:"add_times"`    // 累加次数(平均次数)
	PulsePeriod uint16  `json:"pulse_period"` // 脉冲周期(单次测量时间)
	PulseWidth  uint16  `json:"pulse_width"`  // 脉冲宽度(探测分辨率)
	LaserPower  uint16  `json:"laser_power"`  // 激光器功率
}

// ChannelBrokenAlarm FiberBroken 断纤信息
type ChannelBrokenAlarm struct {
	Info     DeviceInfo `json:"info"`     // 设备信息
	Position float32    `json:"position"` // 断纤位置
	At       time.Time  `json:"at"`       // 报警时间
}

// ChannelTemperatureAlarm 报警信息
type ChannelTemperatureAlarm struct {
	Info   DeviceInfo `json:"info"`             // 设备信息
	Alarms []Alarm    `json:"alarms,omitempty"` // 报警数据
	Type   AlarmType  `json:"type"`             // 报警类型
	At     time.Time  `json:"at"`               // 报警时间
}

type Alarm struct {
	AreaNumber   int16   `json:"area_number"`            // 分区号
	Position     float32 `json:"position"`               // 报警位置
	Temperature  float32 `json:"temperature"`            // 报警温度
	Temperature2 float32 `json:"temperature2,omitempty"` // 报警温度
}

func (a Alarm) String() string {
	return fmt.Sprintf("区域号: %d,报警位置: %.2fm, 报警温度: %.f℃", a.AreaNumber, a.Position, a.Temperature)
}

func (a *ChannelBrokenAlarm) From(data []byte) error {
	return json.Unmarshal(data, a)
}

func (a *ChannelTemperatureAlarm) From(data []byte) error {
	return json.Unmarshal(data, a)
}

func (a *ChannelTemperatureAlarm) AlarmsString() string {
	str := ""
	for _, alarm := range a.Alarms {
		str += alarm.String() + "\n"
	}
	return str
}
